package group.rober.sql.core;

import com.alibaba.druid.sql.SQLUtils;
import group.rober.runtime.kit.JSONKit;
import group.rober.runtime.kit.MapKit;
import group.rober.runtime.kit.NumberKit;
import group.rober.runtime.model.PaginationData;
import group.rober.sql.dialect.SqlDialect;
import group.rober.sql.dialect.SqlDialectType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

/**
 * 抽象通过查询
 */
public class AbstractQuery {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    protected SqlDialectType sqlDialectType = SqlDialectType.MYSQL;
    protected NamedParameterJdbcTemplate jdbcTemplate;

    public SqlDialectType getSqlDialectType() {
        return sqlDialectType;
    }

    public void setSqlDialectType(SqlDialectType sqlDialectType) {
        this.sqlDialectType = sqlDialectType;
    }

    public NamedParameterJdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    public void setJdbcTemplate(NamedParameterJdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    protected String prettySqlFormat(String sql){
        return SQLUtils.format(sql,sqlDialectType.name().toLowerCase(),new SQLUtils.FormatOption(true,true));
    }

    public <T> PaginationData<T> selectListPagination(PaginationQuery query, RowMapper<T> rowMapper){
        SqlDialect sqlDialect = getSqlDialect();
        String sql = query.getQuery();

        long startTime = System.currentTimeMillis();
        logger.debug("[====================SQL分页查询====================][开始]");
        //根据不同的数据库方言，选择合适的策略处理分页
        String paginationSql = sqlDialect.getPaginationSql(sql,query.getIndex(),query.getSize());
        logger.debug(prettySqlFormat(paginationSql));
        logger.debug("参数:"+ JSONKit.toJsonStringNowrap(query.getParameterMap()));

        List<T> dataList = jdbcTemplate.query(paginationSql,query.getParameterMap(),rowMapper);
        long endTime = System.currentTimeMillis();
        logger.debug("耗时:("+ (endTime-startTime)+")毫秒");
        logger.debug("[====================SQL分页查询====================][结束]");
        int totalCount = selectCount(sql,query.getParameterMap());
        int pageCount = NumberKit.ceil(NumberKit.divide(totalCount,query.getSize()),0).intValue();

        PaginationData pqr = new PaginationData();
        pqr.setDataList(dataList);
        pqr.setIndex(query.getIndex());
        pqr.setSize(query.getSize());
        pqr.setRowCount(dataList.size());
        pqr.setTotalRowCount(totalCount);
        pqr.setPageCount(pageCount);

        return pqr;
    }

    public Integer selectCount(String sql,Map<String,?> paramMap){
        SqlDialect sqlDialect = getSqlDialect();
        String countSql = sqlDialect.getCountSql(sql);

        return jdbcTemplate.queryForObject(countSql, paramMap, new RowMapper<Integer>() {
            public Integer mapRow(ResultSet rs, int rowNum) throws SQLException {
                return rs.getInt(1);
            }
        });

    }

    public SqlDialect getSqlDialect(){
        SqlDialect sqlDialect = SqlConsts.DIALECT_MAP.get(sqlDialectType);
        if(sqlDialect==null){
            throw new UnsupportedOperationException(sqlDialectType.name()+" database type is not supported");
        }
        return sqlDialect;
    }

    public Integer selectCount(String sql,String k1,Object v1){
        return selectCount(sql, MapKit.mapOf(k1,v1));
    }
    public Integer selectCount(String sql,String k1,Object v1,String k2,Object v2){
        return selectCount(sql,MapKit.mapOf(k1,v1,k2,v2));
    }
    public Integer selectCount(String sql,String k1,Object v1,String k2,Object v2,String k3,Object v3){
        return selectCount(sql,MapKit.mapOf(k1,v1,k2,v2,k3,v3));
    }
}
